/*
 * dal progetto su google code: jwang302-project
 * http://code.google.com/p/jwang302-project/source/browse/trunk/Proproceptive+Vision/src/gatech/edu/vision/util/HistogramCompareUtil.java?spec=svn22&r=22 
 */

package gestoreImmagini;

import java.util.ArrayList;
import java.util.List;

import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;

public class HistogramCompareUtil {
        static int maskCounter=0;
        public static List<Mat> RGBHistCalc(Bitmap bitmap, Bitmap mask_bitmap) {
                
                
                String imagePath = "/sdcard/MyImages/";
                
//              
//              FileOutputStream out;
//              try {
//                      out = new FileOutputStream(imagePath+"mask"+maskCounter+".png");
//                      mask_bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
//              } catch (FileNotFoundException e) {
//                      e.printStackTrace();
//              }
//              
//              
//              maskCounter++;
                
                
                Bitmap converted_image = JPEGtoRGB888(bitmap);
                Bitmap converted_mask = JPEGtoRGB888(mask_bitmap);
                
                Mat imageMat = new Mat();
                imageMat =      Utils.bitmapToMat(converted_image);
                Mat maskMat = new Mat(); 
                maskMat=Utils.bitmapToMat(converted_mask);              
                
                List<Mat> channels = new ArrayList<Mat>();
                for (int i = 0; i < imageMat.channels()-1; i++) {
                        Mat cha = new Mat(imageMat.height(), imageMat.width(),CvType.CV_8UC1);
                        channels.add(cha);
                }
                Core.split(imageMat, channels);
                                                
                List<Integer> numChannels = new ArrayList<Integer>();
                for (int i = 0; i < imageMat.channels()-1; i++) {
                        numChannels.add(i);
                }
                List<Float> ranges = new ArrayList<Float>();
                for (int i = 0; i < imageMat.channels()-1; i++) {
                        ranges.add(0.0F);
                        ranges.add(256.0F);
                }
                

                int hist_size =20;
                List<Integer> histSizes = new ArrayList<Integer>();
                for (int i = 0; i < imageMat.channels()-1; i++) {
                        histSizes.add(hist_size);
                }
                
                
                Mat gray_mask = new Mat(maskMat.height(), maskMat.width(),
                                CvType.CV_8UC1);
                Imgproc.cvtColor(maskMat, gray_mask, Imgproc.COLOR_RGB2GRAY);
                
                
                
                
                Mat hist = new Mat();
                List<Mat> histograms = new ArrayList<Mat>();
                
                //Mat null_mask = new Mat();
                
                for(int i=0; i<channels.size()-1; i++){
                        
                        List<Mat> calcImage = new ArrayList<Mat>();
                        calcImage.add(channels.get(i));
                        List<Integer> calcChannels = new ArrayList<Integer>();
                        calcChannels.add(0);
                        List<Float> calcRanges = new ArrayList<Float>();
                        calcRanges.add(0.0F);
                        calcRanges.add(256.0F);
                        List<Integer> calcSizes = new ArrayList<Integer>();
                        calcSizes.add(histSizes.get(i));
                        Imgproc.calcHist(calcImage, calcChannels, gray_mask, hist,calcSizes, calcRanges);
//                      String output ="";
//                      for(int j=0; j<hist.cols(); j++){
//                              for(int k=0; k<hist.rows(); k++){
//                                      float[] data = new float[1];
//                                      hist.get(k, j, data);
//                                      output+= (float)data[0]+",";
//                              }
//                              output+="\n";
//                      }
//                      System.out.println(output);
//                      output="";
                        
                        Scalar sumScalar = Core.sumElems(hist);
                        double sum = sumScalar.val[0];

                        Mat normalizer = getNormalizer(hist.height(),hist.width(), sum, hist.type());
                        Mat normalizedHist =new Mat(hist.height(), hist.width(),hist.type());
                        
                        Core.divide(hist, normalizer, normalizedHist);
//                      String output ="";
//                      histograms.add(normalizedHist);
//                      for(int j=0; j<normalizedHist.cols(); j++){
//                              for(int k=0; k<normalizedHist.rows(); k++){
//                                      float[] data = new float[1];
//                                      normalizedHist.get(k, j, data);
//                                      output+= (float)data[0]+",";
//                              }
//                              output+="\n";
//                      }
//                      System.out.println(output);
//                      System.out.println("Histogram calc done.");
                }
                imageMat.release();
                maskMat.release();
                hist.release();
                
                return histograms;
                
                
//              Imgproc.calcHist(channels, numChannels, gray_mask, histogram,histSizes, ranges);
//              String output ="";
//              for(int i=0; i<histogram.cols(); i++){
//                      for(int j=0; j<histogram.rows(); j++){
//                              byte[] data = new byte[1];
//                              histogram.get(j, i, data);
//                              output+= (int)data[0]+",";
//                      }
//                      output+="\n";
//              }
//              
//              System.out.println(output);
//              System.out.println("Histogram calc done.");
        }
        
        
        
        

        public static List<Mat> HSVHistCalc(Bitmap bitmap, Bitmap mask_bitmap) {
                
                
                Bitmap converted_image = JPEGtoRGB888(bitmap);
                Bitmap converted_mask = JPEGtoRGB888(mask_bitmap);
                
                Mat imageMat = Utils.bitmapToMat(converted_image);
                Mat maskMat = Utils.bitmapToMat(converted_mask);

                Imgproc.cvtColor(imageMat, imageMat, Imgproc.COLOR_RGB2HSV);
                Imgproc.cvtColor(maskMat, maskMat, Imgproc.COLOR_RGB2HSV);
                
                List<Mat> channels = new ArrayList<Mat>();
                for (int i = 0; i < imageMat.channels()-1; i++) {
                        Mat cha = new Mat(imageMat.height(), imageMat.width(),CvType.CV_8UC1);
                        channels.add(cha);
                }
                Core.split(imageMat, channels);
                                                
                List<Integer> numChannels = new ArrayList<Integer>();
                for (int i = 0; i < imageMat.channels(); i++) {
                        numChannels.add(i);
                }
                List<Float> ranges = new ArrayList<Float>();
                for (int i = 0; i < imageMat.channels(); i++) {
                        ranges.add(0.0F);
                        ranges.add(256.0F);
                }
                

                int hist_size =20;
                List<Integer> histSizes = new ArrayList<Integer>();
                for (int i = 0; i < imageMat.channels(); i++) {
                        histSizes.add(hist_size);
                }
                
                
                Mat gray_mask = new Mat(maskMat.height(), maskMat.width(),
                                CvType.CV_8UC1);
                Imgproc.cvtColor(maskMat, gray_mask, Imgproc.COLOR_RGB2GRAY);
//              byte[] maskData = new byte[1];
//              for(int j=0; j<gray_mask.cols(); j++){
//                      for(int k=0; k<gray_mask.rows(); k++){
//                              gray_mask.get(k, j, maskData);
//                              if(maskData[0]!=0){
//                                      System.out.println();
//                              }
//                      }
//              }
                
                Mat hist = new Mat();
                
                

                List<Mat> histograms = new ArrayList<Mat>();
                
                //Mat null_mask = new Mat();
                
                for(int i=0; i<channels.size(); i++){
                        List<Mat> calcImage = new ArrayList<Mat>();
                        calcImage.add(channels.get(i));
                        List<Integer> calcChannels = new ArrayList<Integer>();
                        calcChannels.add(0);
                        List<Float> calcRanges = new ArrayList<Float>();
                        calcRanges.add(0.0F);
                        calcRanges.add(256.0F);
                        List<Integer> calcSizes = new ArrayList<Integer>();
                        calcSizes.add(histSizes.get(i));
                        Imgproc.calcHist(calcImage, calcChannels, gray_mask, hist,calcSizes, calcRanges);
//                      String output ="";
//                      for(int j=0; j<hist.cols(); j++){
//                              for(int k=0; k<hist.rows(); k++){
//                                      float[] data = new float[1];
//                                      hist.get(k, j, data);
//                                      output+= (float)data[0]+",";
//                              }
//                              output+="\n";
//                      }
//                      System.out.println(output);
//                      output="";
                        
                        Scalar sumScalar = Core.sumElems(hist);
                        double sum = sumScalar.val[0];

                        Mat normalizer = getNormalizer(hist.height(),hist.width(), sum, hist.type());
                        Mat normalizedHist =new Mat(hist.height(), hist.width(),hist.type());
                        
                        Core.divide(hist, normalizer, normalizedHist);
                        histograms.add(normalizedHist);
//                      for(int j=0; j<normalizedHist.cols(); j++){
//                              for(int k=0; k<normalizedHist.rows(); k++){
//                                      float[] data = new float[1];
//                                      normalizedHist.get(k, j, data);
//                                      output+= (float)data[0]+",";
//                              }
//                              output+="\n";
//                      }
//                      System.out.println(output);
//                      System.out.println("Histogram calc done.");
                }
                
                return histograms;
                
                
//              Imgproc.calcHist(channels, numChannels, gray_mask, histogram,histSizes, ranges);
//              String output ="";
//              for(int i=0; i<histogram.cols(); i++){
//                      for(int j=0; j<histogram.rows(); j++){
//                              byte[] data = new byte[1];
//                              histogram.get(j, i, data);
//                              output+= (int)data[0]+",";
//                      }
//                      output+="\n";
//              }
//              
//              System.out.println(output);
//              System.out.println("Histogram calc done.");
        }
        
        public static List<Mat> HSVHistCalc(Bitmap bitmap) {
            
            
            Bitmap converted_image = JPEGtoRGB888(bitmap);

            
            Mat imageMat = Utils.bitmapToMat(converted_image);
            Mat maskMat = new Mat();

            Imgproc.cvtColor(imageMat, imageMat, Imgproc.COLOR_RGB2HSV);
//            Imgproc.cvtColor(maskMat, maskMat, Imgproc.COLOR_RGB2HSV);
            
            List<Mat> channels = new ArrayList<Mat>();
            for (int i = 0; i < imageMat.channels()-1; i++) {
                    Mat cha = new Mat(imageMat.height(), imageMat.width(),CvType.CV_8UC1);
                    channels.add(cha);
            }
            Core.split(imageMat, channels);
                                            
            List<Integer> numChannels = new ArrayList<Integer>();
            for (int i = 0; i < imageMat.channels(); i++) {
                    numChannels.add(i);
            }
            List<Float> ranges = new ArrayList<Float>();
            for (int i = 0; i < imageMat.channels(); i++) {
                    ranges.add(0.0F);
                    ranges.add(256.0F);
            }
            

            int hist_size =20;
            List<Integer> histSizes = new ArrayList<Integer>();
            for (int i = 0; i < imageMat.channels(); i++) {
                    histSizes.add(hist_size);
            }
            
            
//            Mat gray_mask = new Mat(maskMat.height(), maskMat.width(),
//                            CvType.CV_8UC1);
//            Imgproc.cvtColor(maskMat, gray_mask, Imgproc.COLOR_RGB2GRAY);
            
            Mat gray_mask = new Mat();
            
//          byte[] maskData = new byte[1];
//          for(int j=0; j<gray_mask.cols(); j++){
//                  for(int k=0; k<gray_mask.rows(); k++){
//                          gray_mask.get(k, j, maskData);
//                          if(maskData[0]!=0){
//                                  System.out.println();
//                          }
//                  }
//          }
            
            Mat hist = new Mat();
            
            

            List<Mat> histograms = new ArrayList<Mat>();
            
            //Mat null_mask = new Mat();
            
            for(int i=0; i<channels.size(); i++){
                    List<Mat> calcImage = new ArrayList<Mat>();
                    calcImage.add(channels.get(i));
                    List<Integer> calcChannels = new ArrayList<Integer>();
                    calcChannels.add(0);
                    List<Float> calcRanges = new ArrayList<Float>();
                    calcRanges.add(0.0F);
                    calcRanges.add(256.0F);
                    List<Integer> calcSizes = new ArrayList<Integer>();
                    calcSizes.add(histSizes.get(i));
                    Imgproc.calcHist(calcImage, calcChannels, gray_mask, hist,calcSizes, calcRanges);
//                  String output ="";
//                  for(int j=0; j<hist.cols(); j++){
//                          for(int k=0; k<hist.rows(); k++){
//                                  float[] data = new float[1];
//                                  hist.get(k, j, data);
//                                  output+= (float)data[0]+",";
//                          }
//                          output+="\n";
//                  }
//                  System.out.println(output);
//                  output="";
                    
                    Scalar sumScalar = Core.sumElems(hist);
                    double sum = sumScalar.val[0];

                    Mat normalizer = getNormalizer(hist.height(),hist.width(), sum, hist.type());
                    Mat normalizedHist =new Mat(hist.height(), hist.width(),hist.type());
                    
                    Core.divide(hist, normalizer, normalizedHist);
                    histograms.add(normalizedHist);
//                  for(int j=0; j<normalizedHist.cols(); j++){
//                          for(int k=0; k<normalizedHist.rows(); k++){
//                                  float[] data = new float[1];
//                                  normalizedHist.get(k, j, data);
//                                  output+= (float)data[0]+",";
//                          }
//                          output+="\n";
//                  }
//                  System.out.println(output);
//                  System.out.println("Histogram calc done.");
            }
            
            return histograms;
            
            
//          Imgproc.calcHist(channels, numChannels, gray_mask, histogram,histSizes, ranges);
//          String output ="";
//          for(int i=0; i<histogram.cols(); i++){
//                  for(int j=0; j<histogram.rows(); j++){
//                          byte[] data = new byte[1];
//                          histogram.get(j, i, data);
//                          output+= (int)data[0]+",";
//                  }
//                  output+="\n";
//          }
//          
//          System.out.println(output);
//          System.out.println("Histogram calc done.");
    }
        
public static Mat grayHistCalc(Mat imageMat) {
            
            List<Mat> channels = new ArrayList<Mat>();
            for (int i = 0; i < imageMat.channels()-1; i++) {
                    Mat cha = new Mat(imageMat.height(), imageMat.width(),CvType.CV_8UC1);
                    channels.add(cha);
            }
            Core.split(imageMat, channels);
                                            
            List<Integer> numChannels = new ArrayList<Integer>();
            for (int i = 0; i < imageMat.channels(); i++) {
                    numChannels.add(i);
            }
            
            List<Float> ranges = new ArrayList<Float>();
            for (int i = 0; i < imageMat.channels(); i++) {
                    ranges.add(0.0F);
                    ranges.add(256.0F);
            }
            
            int hist_size =20;
            List<Integer> histSizes = new ArrayList<Integer>();
            for (int i = 0; i < imageMat.channels(); i++) {
                    histSizes.add(hist_size);
            }
            
            Mat gray_mask = new Mat();
                       
            Mat hist = new Mat();

           
            List<Mat> calcImage = new ArrayList<Mat>();
            calcImage.add(channels.get(0));
            List<Integer> calcChannels = new ArrayList<Integer>();
            calcChannels.add(0);
            List<Float> calcRanges = new ArrayList<Float>();
            calcRanges.add(0.0F);
            calcRanges.add(256.0F);
            List<Integer> calcSizes = new ArrayList<Integer>();
            calcSizes.add(histSizes.get(0));
            Imgproc.calcHist(calcImage, calcChannels, gray_mask, hist,calcSizes, calcRanges);
           
            Scalar sumScalar = Core.sumElems(hist);
            double sum = sumScalar.val[0];

            Mat normalizer = getNormalizer(hist.height(),hist.width(), sum, hist.type());
            Mat normalizedHist =new Mat(hist.height(), hist.width(),hist.type());
            
            Core.divide(hist, normalizer, normalizedHist);
            
            
            return normalizedHist;
    }
        
        
        

        /**
         * Takes a JPEG captured by the device camera and converts it to RGB888
         * format
         */
        private static Bitmap JPEGtoRGB888(Bitmap img) {
                int numPixels = img.getWidth() * img.getHeight();
                int[] pixels = new int[numPixels];
                // Get JPEG pixels. Each int is the color values for one pixel.
                img.getPixels(pixels, 0, img.getWidth(), 0, 0, img.getWidth(), img
                                .getHeight());
                // Create a Bitmap of the appropriate format.
                Bitmap result = Bitmap.createBitmap(img.getWidth(), img.getHeight(),
                                Config.ARGB_8888);
                // Set RGB pixels.
                result.setPixels(pixels, 0, result.getWidth(), 0, 0, result.getWidth(),
                                result.getHeight());
                return result;
        }
        
        
        
        
        
        
        private static Mat getNormalizer(int height, int width, double value, int cvType){
                double data [] = {value};
                Mat normalizer =new Mat(height, width, cvType);
                for(int j=0; j<normalizer.cols(); j++){
                        for(int k=0; k<normalizer.rows(); k++){
                                normalizer.put(k, j, data);
                        }
                }
                return normalizer;
        }
        
}